/*
  Autore: Andrea Giammanco (http://cern.ch/andrea.giammanco).
  Revisioni:
  A.Lusiani, 19/10/2004:
  - corretta sintassi puntatore myAn
  - indentazione C++
  - migliorati commenti
  - cambiato nome e rimpiazzato main() con nome
  - eliminati colori, corretto aggiornamento visualizzazione

  Scopo di questo programma: valutare la rendita per un cliente 
  delle obbligazioni delle Poste Italiane 
  (http://www.poste.it/bancoposta/premium/scheda_premium.shtml), 
  assumendo funzioni di distribuzione arbitrarie per le variazioni 
  dei tre indici di riferimento.
  La "cedola variabile" e' data da una certa percentuale [62%] 
  della somma pesata dei tre indici (con peso maggiore [60%] per 
  l'indice piu' alto, minore [40%] per il secondo e nullo per il 
  piu' basso), e al cliente viene corrisposto il massimo tra la 
  cedola variabile e un minimo garantito [8%].
  
  Come usarlo in ROOT (http://root.cern.ch):

    root labFisObblStrut.cc <return>

  oppure

    root <return>
    root [0] .x labFisObblStrut.cc

*/

void labFisObblStrut()
{
  gROOT->Reset();
  
  // Create a new canvas.
  c1 = new TCanvas("c1", " ", 200, 10 , 700, 500);
  // c1->SetFillColor(42);
  // c1->GetFrame()->SetFillColor(21);
  c1->GetFrame()->SetBorderSize(6);
  c1->GetFrame()->SetBorderMode(-1);
  
  // Create a new ROOT binary machine independent file.
  // This file is now becoming the current directory.
  
  TFile *hfile = gROOT->FindObject("hsimple.root"); if (hfile) hfile->Close();
  hfile =
    new TFile("hsimple.root","RECREATE","Demo ROOT file with histograms");
  
  // Create some histograms, a profile histogram and an ntuple
  Float_t low = -1.;
  Float_t high = 1.;
  ha = new TH1F("ha","Index A",100,low,high);
  hb = new TH1F("hb","Index B",100,low,high);
  hc = new TH1F("hc","Index C",100,low,high);
  hcedola = new TH1F("cedola","Cedola variabile",100,low,high);
  hfinal = new TH1F("final","Calcolo finale",100,low,high);
  
  //  Set canvas/frame attributes (save old attributes)
  // hcedola->SetFillColor(48);
  hcedola->Draw();

  UInt_t nIter(5000);

  cout << "Simulazione Monte Carlo rendimento obbligazione strutturata"
       << ", " << nIter << " iterazioni"
       << endl;

  gBenchmark->Start("hsimple");
  
  // Parameters:
  const Float_t partecipazione = .62;
  const Float_t garantito = .08;
  
  gRandom->SetSeed();
  const Int_t kUPDATE = 100;
  Float_t a,b,c;
  Float_t sum,cedola_variabile,final;
  // Loop over "experiments":

  for (Int_t i=0; i < nIter; i++) {
    /*    a=gRandom->Gaus(0.,.5);
	  b=gRandom->Gaus(0.,.5);
	  c=gRandom->Gaus(0.,.5);*/
    a=gRandom->Rndm(1.)-0.5;
    b=gRandom->Rndm(1.)-0.5;
    c=gRandom->Rndm(1.)-0.5;
    /*    a=gRandom->Landau(0.,.5);
	  b=gRandom->Landau(0.,.5);
	  c=gRandom->Landau(0.,.5);*/
    ha->Fill(a);
    hb->Fill(b);
    hc->Fill(c);
    myAn = new Analysis(a,b,c);
    myAn->order();
    sum = myAn->weightedSum(6.,4.,0.);
    cedola_variabile = partecipazione*sum;
    hcedola->Fill(cedola_variabile);
    final = max(garantito,cedola_variabile);
    hfinal->Fill(final);
    if ((i%kUPDATE) == (kUPDATE-1)) {
      c1->Modified();
      c1->Update();
    }
    delete myAn;
  }

  gBenchmark->Show("hsimple");
  c1->Modified();
  c1->Update();
  
  // Save all objects in this file
  hcedola->SetFillColor(0);
  hfile->Write();
  hcedola->SetFillColor(48);
  
  // Note that the file is automatically closed when application terminates
  // or when the file destructor is called.
}

Float_t max(Float_t x, Float_t y) {
  if (x>y) {
    return x;
  } else {
    return y;
  }
}

class Analysis {
public:
  Analysis(Float_t a, Float_t b, Float_t c);
  void order();
  Float_t x();
  Float_t y();
  Float_t z();
private:
  Float_t a_,b_,c_;
  Float_t x_,y_,z_;
};

Analysis::Analysis(Float_t a,Float_t b,Float_t c) {
  a_=a;
  b_=b;
  c_=c;
}

void Analysis::order() {
  /* x_=a_;
     y_=b_;
     z_=c_; */
  if (a_>b_ && b_>c_) {
    x_=a_;
    y_=b_;
    z_=c_;
  } elseif (a_>b_ && a_>c_ && b_<c_) {
    x_=a_;
    y_=c_;
    z_=b_;
  } elseif (b_>a_ && a_>c_) {
    x_=b_;
    y_=a_;
    z_=c_;
  } elseif (b_>a_ && b_>c_ && a_<c_) {
    x_=b_;
    y_=c_;
    z_=a_;
  } elseif (c_>a_ && a_>b_) {
    x_=c_;
    y_=a_;
    z_=b_;
  } elseif (c_>a_ && c_>b_ && b_>a_) {
    x_=c_;
    y_=b_;
    z_=a_;
  }
}

Float_t Analysis::x() {
  return x_;
}
Float_t Analysis::y() {
  return y_;
}
Float_t Analysis::z() {
  return z_;
}

Float_t Analysis::weightedSum(Float_t w1, Float_t w2, Float_t w3) {
  return (w1*x_+w2*y_+w3*z_)/(w1+w2+w3);
}
